﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Telerik.Web.UI;

/// <summary>
/// RadTreeView数据绑定
/// </summary>
public class RadTreeViewBinder
{
    DataTable nodesTable = null;
    Action<RadTreeNode> addNode;
    string navTarget;
    bool loadDisabledNode;

    /// <summary>
    /// RadTreeView数据绑定
    /// </summary>
    /// <param name="navTarget">链接目标，不设置不加载链接</param>
    public RadTreeViewBinder(string navTarget)
    {
        this.navTarget = navTarget;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="loadDisabledNode">是否加载禁用的节点</param>
    public RadTreeViewBinder(bool loadDisabledNode)
    {
        this.loadDisabledNode = loadDisabledNode;
    }

    #region 延迟加载
    /// <summary>
    /// 准备数据，各个节点相关的子节点数量
    /// </summary>
    private void PrepareData()
    {
        if (nodesTable == null)
        {
            string sql = string.Format("select count(*) childsCount, m_parentid from lt_Menu where {0} m_parentid<>0 group by m_parentid", loadDisabledNode ? string.Empty : "m_disabled=0 and");
            nodesTable = SqlHelper.Instance.ExecuteDataset(sql).Tables[0];
        }
    }

    /// <summary>
    /// 设置展开模式
    /// ServerSideCallBack表示当前节点下还有子节点，展开后从服务器端加载
    /// </summary>
    /// <param name="node"></param>
    private void SetExpandMode(RadTreeNode node)
    {
        PrepareData();
        bool hasChild = nodesTable.Select("m_parentid=" + node.Value).Length > 0;//是否包含子节点
        node.ExpandMode = hasChild ? TreeNodeExpandMode.ServerSideCallBack : TreeNodeExpandMode.ClientSide;
    }

    /// <summary>
    /// 加载节点
    /// </summary>
    /// <param name="parentId"></param>
    private void LoadNodes(string parentId)
    {
        string sql = string.Format("select m_id,m_name,m_url,m_icon,m_sortIndex from lt_Menu where m_parentid=@parentid {0} order by m_sortIndex asc", loadDisabledNode ? string.Empty : "and m_disabled=0");

        SqlParameter parentIdParameter = SqlParameterEx.CreateParameter("@parentid", SqlDbType.Int, parentId);
        using (IDataReader reader = SqlHelper.Instance.ExecuteReader(sql, parentIdParameter))
        {
            while (reader.Read())
            {
                RadTreeNode node = CreateNode(reader);
                addNode(node);
            }
        }
    }

    /// <summary>
    /// 创建节点
    /// </summary>
    /// <param name="reader"></param>
    /// <returns></returns>
    private RadTreeNode CreateNode(IDataReader reader)
    {
        RadTreeNode node = new RadTreeNode(reader.GetString(1), reader.GetInt32(0).ToString());
        string navUrl = reader.GetString(2);
        if (!string.IsNullOrEmpty(navTarget) &&
            !string.IsNullOrEmpty(navUrl))
        {
            node.NavigateUrl = navUrl;
            node.Target = navTarget;
        }
        string icon = reader.GetString(3);
        if (!string.IsNullOrEmpty(icon))
            node.ImageUrl = icon;
        SetExpandMode(node);
        return node;
    }

    /// <summary>
    /// 节点展开时加载子节点数据
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void TreeNodeExpand(object sender, RadTreeNodeEventArgs e)
    {
        LoadChildNodes(e.Node);
    }

    /// <summary>
    /// 加载顶级节点
    /// </summary>
    /// <param name="treeView"></param>
    public void LoadTopNodes(RadTreeView treeView)
    {
        treeView.NodeExpand += TreeNodeExpand;
        this.addNode = treeView.Nodes.Add;
        LoadNodes("0");
    }

    /// <summary>
    /// 加载子节点
    /// </summary>
    /// <param name="parentNode"></param>
    public void LoadChildNodes(RadTreeNode parentNode)
    {
        this.addNode = parentNode.Nodes.Add;
        LoadNodes(parentNode.Value);
        parentNode.Expanded = true;
    }
    #endregion

    /// <summary>
    /// 加载所有节点
    /// </summary>
    /// <param name="treeview"></param>
    public void LoadAllNodes(RadTreeView treeview)
    {
        LoadAllNodes(treeview, string.Empty);
    }

    /// <summary>
    /// 加载所有节点
    /// </summary>
    /// <param name="treeview"></param>
    /// <param name="condition"></param>
    public void LoadAllNodes(RadTreeView treeview, string condition)
    {
        StringBuilder builder = new StringBuilder("select * from lt_Menu");
        if (!loadDisabledNode)
        {
            builder.Append(" where m_disabled=0 ");
        }
        if (!string.IsNullOrEmpty(condition))
        {
            builder.Append(loadDisabledNode ? " where " : " and ");
            builder.Append(condition);
        }
        builder.Append(" order by m_sortIndex asc");

        treeview.NodeDataBound += new RadTreeViewEventHandler(treeview_NodeDataBound);
        treeview.DataSource = SqlHelper.Instance.ExecuteReader(builder.ToString());
        treeview.DataTextField = "m_name";
        treeview.DataValueField = "m_id";
        treeview.DataFieldID = "m_id";
        treeview.DataFieldParentID = "m_parentid";
        if (!string.IsNullOrEmpty(navTarget))
            treeview.DataNavigateUrlField = "m_url";
        treeview.DataBind();
    }

    /// <summary>
    /// 把数据库字段绑定到自定义属性上以备后用
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void treeview_NodeDataBound(object sender, RadTreeNodeEventArgs e)
    {
        IDataRecord dataRowView = (IDataRecord)e.Node.DataItem;
        e.Node.Attributes["sortIndex"] = dataRowView["m_sortIndex"].ToString();
        e.Node.Attributes["parentId"] = dataRowView["m_parentId"].ToString();
        e.Node.Attributes["url"] = dataRowView["m_url"].ToString();
        //e.Node.Attributes["icon"] = e.Node.ImageUrl = dataRowView["m_icon"].ToString();
        if (!string.IsNullOrEmpty(navTarget) &&
            !string.IsNullOrEmpty(e.Node.NavigateUrl))
        {
            e.Node.Target = navTarget;
        }
    }

    /// <summary>
    /// RadTreeView数据绑定
    /// 延迟加载
    /// </summary>
    /// <param name="treeview"></param>
    /// <param name="target">链接目标，不设置不加载链接</param>
    public static RadTreeViewBinder LoadOnDemand(RadTreeView treeview, string target)
    {
        RadTreeViewBinder loader = new RadTreeViewBinder(target);
        loader.LoadTopNodes(treeview);
        return loader;
    }

    /// <summary>
    /// RadTreeView数据绑定
    /// 延迟加载
    /// </summary>
    /// <param name="treeview"></param>
    /// <param name="loadDisabledNode">是否加载禁用的节点</param>
    public static RadTreeViewBinder LoadOnDemand(RadTreeView treeview, bool loadDisabledNode)
    {
        RadTreeViewBinder loader = new RadTreeViewBinder(loadDisabledNode);
        loader.LoadTopNodes(treeview);
        return loader;
    }
}